#ifndef __SKIP_H__
#define __SKIP_H__
#include "Utile.hpp"
#include "Message.hpp"
#include "Formatter.hpp"
#include <iostream>
#include <memory>
#include <mutex>
namespace ssslog
{
    //工厂模式
    class LogSink 
    {
    public:
        using ptr = std::shared_ptr<LogSink>;
        LogSink() {}
        ~LogSink() {}
        virtual void Log(const char* data, size_t len) = 0;//纯虚函数
    };
    
    class StdoutSink :public LogSink
    {
    public:
        using ptr = std::shared_ptr<StdoutSink>;
        StdoutSink() = default;
        virtual void Log(const char* data, size_t len) { std::cout.write(data, len);}
    };
    class FileSink : public LogSink
    {
    public:
        using ptr = std::shared_ptr<FileSink>;
        FileSink(const std::string& filename):_filename(filename) 
        {
            File::CreatDirectory(File::Path(filename));
            _ofs.open(_filename, std::ios::binary | std::ios::app);
            assert(_ofs.is_open());
            
        }
        virtual void Log(const char* data,size_t len)
        {
            _ofs.write((const char*)data, len);
            if (_ofs.good() == false) std::cout << "输出日志失败！" << std::endl;
        }
    private:
        std::string _filename;
        std::ofstream _ofs;
    };
    class RollSkip :public LogSink
    {
    public:
        using ptr = std::shared_ptr<FileSink>;
        RollSkip(const std::string basename,size_t max_fsize,size_t cur_fsize = 0)
        :_basename(basename), _max_fsize(max_fsize),_cur_fsize(cur_fsize)
        {
            File::CreatDirectory(File::Path(_basename));
        }
        virtual void Log(const char* data,size_t len)
        {
            InitLogFile();//初始化文件
            _ofs.write(data, len);
            if (_ofs.good() == false) {
                std::cout << "日志输出文件失败！\n";
            }
            _cur_fsize += len;
        }
    private:
        void InitLogFile()
        {
            if (_ofs.is_open() == false || _cur_fsize >= _max_fsize) 
            {
                _ofs.close();
                std::string name = CreatFileName();
                _ofs.open(name, std::ios::binary | std::ios::app);
                assert(_ofs.is_open());
                _cur_fsize = 0;
                return;
            }
            return;
        }
        std:: string CreatFileName()
        {
            time_t t = time(NULL);
            struct tm lt;
            localtime_r(&t, &lt);
            std::stringstream ss;
            ss << _basename;
            ss << lt.tm_year + 1900;
            ss << lt.tm_mon + 1;
            ss << lt.tm_mday;
            ss << lt.tm_hour;
            ss << lt.tm_min;
            ss << lt.tm_sec;
            ss << ".log";
            return ss.str();
        }
    private:
        std::string _basename;
        std::ofstream _ofs;
        size_t _max_fsize;
        size_t _cur_fsize;
    };

    class SinkFactory 
    {
    public:
        template<class SinkType,class ...Args>
        static LogSink::ptr Create(Args&& ...args)
        {
            return std::make_shared<SinkType>(std::forward<Args>(args)...);
        }
    };
}
#endif 
